package system

import (
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/asynkron/protoactor-go/actor"
)

// SimpleSupervisor is a simple workflow supervisor
type SimpleSupervisor struct {
	// workflows are the deployed workflows
	workflows map[string]interface{}
	// mu is a mutex for protecting the workflows
	mu sync.RWMutex
	// logger is the supervisor logger
	logger *log.Logger
}

// NewSimpleSupervisor creates a new simple supervisor
func NewSimpleSupervisor() actor.Actor {
	return &SimpleSupervisor{
		workflows: make(map[string]interface{}),
		logger:    log.New(log.Writer(), "[SimpleSupervisor] ", log.LstdFlags),
	}
}

// Receive handles messages for the simple supervisor
func (s *SimpleSupervisor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case *actor.Started:
		s.handleStarted(context)
	case *actor.Stopping:
		s.handleStopping(context)
	case *DeployWorkflowCommand:
		s.handleDeployWorkflow(context, msg)
	case *StartWorkflowCommand:
		s.handleStartWorkflow(context, msg)
	case *StopWorkflowCommand:
		s.handleStopWorkflow(context, msg)
	case *GetWorkflowStatusCommand:
		s.handleGetWorkflowStatus(context, msg)
	default:
		// Try to handle as a list workflows command
		if fmt.Sprintf("%T", msg) == "*struct {}" {
			s.handleListWorkflows(context)
		} else {
			s.logger.Printf("Received unknown message: %T", msg)
		}
	}
}

// handleStarted handles the Started message
func (s *SimpleSupervisor) handleStarted(context actor.Context) {
	s.logger.Println("Simple supervisor started")
}

// handleStopping handles the Stopping message
func (s *SimpleSupervisor) handleStopping(context actor.Context) {
	s.logger.Println("Simple supervisor stopping")
}

// handleDeployWorkflow handles the DeployWorkflowCommand message
func (s *SimpleSupervisor) handleDeployWorkflow(context actor.Context, msg *DeployWorkflowCommand) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Check if workflow already exists
	if _, exists := s.workflows[msg.WorkflowID]; exists {
		context.Respond(&DeployWorkflowResponse{
			Success: false,
			Error:   fmt.Sprintf("workflow already exists: %s", msg.WorkflowID),
		})
		return
	}

	// Store workflow definition
	s.workflows[msg.WorkflowID] = msg.Definition

	// Respond with success
	context.Respond(&DeployWorkflowResponse{
		Success: true,
	})

	s.logger.Printf("Deployed workflow: %s", msg.WorkflowID)
}

// handleStartWorkflow handles the StartWorkflowCommand message
func (s *SimpleSupervisor) handleStartWorkflow(context actor.Context, msg *StartWorkflowCommand) {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Get workflow ID from parameters
	workflowID := ""
	if msg.Parameters != nil {
		if id, ok := msg.Parameters["workflowID"].(string); ok {
			workflowID = id
		}
	}

	// Check if workflow exists
	if _, exists := s.workflows[workflowID]; !exists {
		context.Respond(&StartWorkflowResponse{
			Success: false,
			Error:   fmt.Sprintf("workflow not found: %s", workflowID),
		})
		return
	}

	// Create run ID
	runID := fmt.Sprintf("%s-%d", workflowID, time.Now().Unix())

	// Respond with success
	context.Respond(&StartWorkflowResponse{
		Success: true,
		RunID:   runID,
	})

	s.logger.Printf("Started workflow: %s with run ID: %s", workflowID, runID)
}

// handleStopWorkflow handles the StopWorkflowCommand message
func (s *SimpleSupervisor) handleStopWorkflow(context actor.Context, msg *StopWorkflowCommand) {
	// Respond with success
	context.Respond(&StopWorkflowResponse{
		Success: true,
	})

	s.logger.Printf("Stopped workflow run: %s", msg.RunID)
}

// handleGetWorkflowStatus handles the GetWorkflowStatusCommand message
func (s *SimpleSupervisor) handleGetWorkflowStatus(context actor.Context, msg *GetWorkflowStatusCommand) {
	// Respond with status
	context.Respond(&GetWorkflowStatusResponse{
		Success:  true,
		Status:   "completed",
		Progress: 100,
	})

	s.logger.Printf("Got status for workflow run: %s", msg.RunID)
}

// WorkflowInfo represents workflow information
type WorkflowInfo struct {
	// ID is the workflow ID
	ID string
	// Name is the workflow name
	Name string
	// Description is the workflow description
	Description string
	// Version is the workflow version
	Version string
}

// ListWorkflowsResponse is the response to a ListWorkflowsCommand
type ListWorkflowsResponse struct {
	// Workflows are the workflows
	Workflows []*WorkflowInfo
}

// handleListWorkflows handles the ListWorkflowsCommand message
func (s *SimpleSupervisor) handleListWorkflows(context actor.Context) {
	s.mu.RLock()
	defer s.mu.RUnlock()

	// Create workflow list
	workflows := make([]*WorkflowInfo, 0, len(s.workflows))
	for id, workflow := range s.workflows {
		// Get workflow name and description
		name := id
		description := ""
		version := ""

		// Try to get name and description from workflow
		if wf, ok := workflow.(map[string]interface{}); ok {
			if n, ok := wf["name"].(string); ok {
				name = n
			}
			if d, ok := wf["description"].(string); ok {
				description = d
			}
			if v, ok := wf["version"].(string); ok {
				version = v
			}
		}

		workflows = append(workflows, &WorkflowInfo{
			ID:          id,
			Name:        name,
			Description: description,
			Version:     version,
		})
	}

	// Respond with workflows
	context.Respond(&ListWorkflowsResponse{
		Workflows: workflows,
	})

	s.logger.Println("Listed workflows")
}
